package srconfig

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"wails/modules/editor/models"
	. "wails/modules/editor/services"

	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/datax/arrayx"
	"gitee.com/zhongguo168a/gocodes/datax/convertx"
	"gitee.com/zhongguo168a/gocodes/datax/mapx"
	"gitee.com/zhongguo168a/gocodes/datax/schemax"
	"gitee.com/zhongguo168a/gocodes/datax/schemax/configx"
	"gitee.com/zhongguo168a/gocodes/datax/stringx"
	"gitee.com/zhongguo168a/gocodes/myx/errorx"
	"github.com/spf13/afero"
	"zhongguo168a.top/mycodes/gocodes/utils/maputil"
)

func ClearDir(fs afero.Fs, dir string) error {
	entries, err := afero.ReadDir(fs, dir)
	if err != nil {
		return fmt.Errorf("读取目录失败: %w", err)
	}

	for _, entry := range entries {
		path := filepath.Join(dir, entry.Name())
		err := fs.RemoveAll(path) // 删除文件或子目录
		if err != nil {
			return fmt.Errorf("删除失败 %s: %w", path, err)
		}
	}
	return nil
}
func (p *ConfigService) Create缩略图(配置 *configx.ConfigTreeItem) (err error) {
	switch 配置.F分类 {
	case "地块":
		资源路径 := maputil.String(配置.Get数据(), "资源路径")
		网格尺寸 := maputil.Int(配置.Get数据(), "网格尺寸")
		switch 配置.L类型 {
		case "地块_瓦片":
			图标, errCreate := create贴片缩略图(models.Module.Get项目路径(), "assets/assets/"+资源路径, 网格尺寸*2)
			if errCreate != nil {
				return errCreate
			}
			maputil.Set(配置.Get数据(), "图标", 图标)
		default:
			图标, errCreate := create图片缩略图(models.Module.Get项目路径(), "assets/assets/"+资源路径)
			if errCreate != nil {
				return errCreate
			}
			maputil.Set(配置.Get数据(), "图标", 图标)
		}
	default:
	}
	return
}

func (p *ConfigService) Do更新资源文件夹() error {
	set, errs := File.GetFileConfig(File.Get资源配置文件列表())
	_ = errs

	configRepo := configx.NewConfigRepo()
	configRepo.Load(set)

	默认配置字典 := map[string]*configx.ConfigTreeItem{
		"图集":  configRepo.GetBy编号("图集_默认"),
		"图标":  configRepo.GetBy编号("图标_默认"),
		"预设":  configRepo.GetBy编号("预设_默认"),
		"音乐":  configRepo.GetBy编号("音乐_默认"),
		"音效":  configRepo.GetBy编号("音效_默认"),
		"纹理":  configRepo.GetBy编号("纹理_默认"),
		"地块":  configRepo.GetBy编号("地块_图片_默认"),
		"模型":  configRepo.GetBy编号("模型_默认"),
		"装饰品": configRepo.GetBy编号("装饰品_地块_默认"),
	}

	分类后缀字典 := map[string][]string{
		"图集":  {".atlas"},
		"图标":  {".png", ".jpg"},
		"预设":  {".prefab"},
		"音乐":  {".ogg"},
		"音效":  {".ogg"},
		"纹理":  {".png", ".jpg"},
		"地块":  {".png", ".jpg"},
		"装饰品": {".png", ".jpg", ".atlas"},
		"模型":  {".png", ".jpg", ".atlas", ".avatar", ".prefab"},
	}

	var 需要创建的配置文件 [][]interface{}
	资源文件列表 := File.Get资源文件列表()
	资源父路径 := models.Module.Get资源路径()

	存在的资源集合 := map[string]bool{}
	for i := 0; i < len(资源文件列表); i++ {
		资源文件 := 资源文件列表[i]
		if 资源文件.IsDir() {
			panic("读取资源文件的目录")
		}
		metaPath := strings.ReplaceAll(资源文件.Path(), 资源父路径+"/", "")
		meta, errMeta := GetMetaFileContent(资源文件.Path())
		if errMeta != nil {
			panic("GetMetaFileContent: " + errMeta.Error())
		}
		importer := mapx.String(meta, "importer")
		if importer == "directory" {
			continue
		}

		_, 主题之后 := stringx.SplitFirstArray(metaPath, "/")
		分类, _ := stringx.SplitFirstArray(主题之后, "/")
		默认配置 := 默认配置字典[分类]
		if 默认配置 == nil {
			panic(fmt.Sprintf("未发现默认配置: 分类=%v 路径=%v\n", 分类, metaPath))
		}

		资源路径 := strings.ReplaceAll(metaPath, ".meta", "")
		主题路径 := 分类 + "/" + strings.Replace(资源路径, "/"+分类, "", 1)

		suffix := filepath.Ext(资源路径)

		分类后缀 := 分类后缀字典[分类]
		if !arrayx.Contains(len(分类后缀), func(i int) bool {
			return 分类后缀[i] == suffix
		}) {
			continue
		}

		名称 := strings.ReplaceAll(资源文件.Name(), suffix+".meta", "")
		uuid := GetMetaUUID(分类, meta)

		存在的配置 := configRepo.GetBy编号(uuid)
		if 存在的配置 == nil { // 配置文件不存在，创建
			新的配置 := 默认配置.Inherit(uuid)
			新的配置.W文件 = ""
			新的配置.M默认 = false
			新的配置.D导出 = 2
			新的配置.M名称 = 名称
			新的配置.Set数据(map[string]interface{}{
				"主题路径": 主题路径,
				"资源路径": 资源路径,
				"名称":   名称,
			})
			需要创建的配置文件 = append(需要创建的配置文件, []interface{}{
				新的配置,
			})
			存在的配置 = 新的配置

			configRepo.Set(新的配置.B编号, 新的配置)
		} else {
			数据 := 存在的配置.Get数据()
			存在的路径 := mapx.String(数据, "资源路径")
			新的路径 := 资源路径
			if 存在的配置.M名称 != 名称 || 存在的路径 != 新的路径 {
				存在的配置.M名称 = 名称
				数据["主题路径"] = 主题路径
				数据["资源路径"] = 新的路径
				数据["名称"] = 名称
			}
			需要创建的配置文件 = append(需要创建的配置文件, []interface{}{
				存在的配置,
			})
		}
		err := p.Create缩略图(存在的配置)
		if err != nil {
			return err
		}

		存在的资源集合[uuid] = true
	}

	// 处理装饰品, 好像不需要, 根据目录随机就可以了
	//{
	//	装饰品集合 := configRepo.DictBy分类("装饰品")
	//	group := 装饰品集合.GroupByCondition(func(s string, item *configx.ConfigTreeItem) string {
	//		return mapx.String(item.Get数据(), "资源路径")
	//	}, nil)
	//
	//	装饰组默认配置 := configRepo.GetBy编号("装饰组_默认")
	//	for 资源路径, dict := range group {
	//		uuid := GetMetaFileUUID(资源路径)
	//		名称 := stringx.SplitLast(资源路径, "/")
	//		装饰组 := func() (x map[string]interface{}) {
	//			index := 0
	//			dict.ForRange(func(key string, item *configx.ConfigTreeItem) (err error) {
	//				x[convertx.AnyToString(index)] = key
	//				index++
	//				return nil
	//			})
	//			return
	//		}()
	//		存在的配置 := configRepo.GetBy编号(uuid)
	//		if 存在的配置 == nil { // 配置文件不存在，创建
	//			新的配置 := 装饰组默认配置.Inherit(uuid)
	//			新的配置.W文件 = ""
	//			新的配置.M默认 = false
	//			新的配置.D导出 = 2
	//			新的配置.M名称 = 名称
	//
	//			存在的配置 = 新的配置
	//
	//			configRepo.Set(新的配置.B编号, 新的配置)
	//		}
	//
	//		存在的配置.Set数据(map[string]interface{}{
	//			"名称":   名称,
	//			"装饰组": 装饰组,
	//		})
	//		需要创建的配置文件 = append(需要创建的配置文件, []interface{}{
	//			存在的配置,
	//		})
	//	}
	//}

	// 每个资源独立一个文件的做法
	for i := 0; i < len(需要创建的配置文件); i++ {
		创建文件信息 := 需要创建的配置文件[i]
		创建的配置 := 创建文件信息[0].(*configx.ConfigTreeItem)

		创建文件内容 := map[string]interface{}{}
		创建文件内容[创建的配置.B编号] = 创建的配置.ToMap()

		//fmt.Println(创建文件, string(创建文件内容))

		文件内容, errJson := json.MarshalIndent(创建文件内容, "", "\t")
		if errJson != nil {
			panic("打包文件: " + errJson.Error())
		}

		if string(文件内容) == "" {
			continue
		}

		创建文件路径 := 创建的配置.F分类 + "/" + 创建的配置.B编号 + ".ycj"
		输出配置路径 := models.Module.Get编辑器路径() + "/config/asset/" + 创建文件路径
		errMkdirAll := os.MkdirAll(filepath.Dir(输出配置路径), os.ModePerm)
		if errMkdirAll != nil {
			return errorx.Wrap(errMkdirAll, "os.MkdirAll", datax.M{"资源路径": errMkdirAll})
		}
		errWrite := os.WriteFile(输出配置路径, 文件内容, os.ModePerm)
		if errWrite != nil {
			return errorx.Wrap(errWrite, "os.WriteFile", datax.M{"资源路径": 创建文件路径})
		}
	}

	return nil
}

func create配置文件() {

}

func (p *ConfigService) 清理无效的资源() {
	set, errs := File.GetFileConfig(File.Get资源配置文件列表())
	_ = errs

	configRepo := configx.NewConfigRepo()
	configRepo.Load(set)
}

func (p *ConfigService) get需要包含的资源(repo *configx.ConfigRepo) []string {
	需要过滤的分类 := func(link string) bool {
		if link == "模型" ||
			link == "图标" ||
			link == "纹理" ||
			link == "地块" ||
			link == "预设" ||
			link == "音效" ||
			link == "音乐" {
			return true
		}
		return false
	}
	需要包含的资源 := map[string]bool{}
	repo.ForRange(func(key string, configItem *configx.ConfigTreeItem) (err error) {
		configItem.WalkField(func(classDecl *schemax.ClassDecl, field *schemax.Field, ival interface{}) {
			link := field.Tags["link"]
			if !需要过滤的分类(link) {
				return
			}
			编号 := convertx.AnyToString(ival)
			if 编号 == "" {
				return
			}

			配置 := repo.GetBy编号(编号)
			if 配置 == nil {
				return
			}
			if 配置.M默认 {
				return
			}

			相对路径 := 配置.M名称

			switch 配置.L类型 {
			case "模型":
				需要包含的资源["模型/"+相对路径] = true
			case "音乐":
				需要包含的资源["音乐/"+相对路径] = true
			case "音效":
				需要包含的资源["音效/"+相对路径] = true
			case "图标":
				需要包含的资源["图标/"+相对路径] = true
			case "预设":
				需要包含的资源["预设/"+相对路径] = true
			case "地块":
				需要包含的资源["地块/"+相对路径] = true
			}
		})
		return nil
	})

	var 需要包含的资源列表 []string
	for key, _ := range 需要包含的资源 {
		需要包含的资源列表 = append(需要包含的资源列表, key)
	}
	sort.Strings(需要包含的资源列表)
	return 需要包含的资源列表
}

func GetMetaFileUUID(filePath string) (x string) {
	// 6. 生成 UUID 和输出路径
	meta, errMeta := GetMetaFileContent(filePath + ".meta")
	if errMeta != nil {
		panic("GetMetaFileContent: " + errMeta.Error())
	}
	return mapx.String(meta, "uuid")
}

func GetMetaFileContent(filePath string) (map[string]interface{}, error) {
	bcontent, err := os.ReadFile(filePath)
	m := map[string]interface{}{}
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(bcontent, &m)
	if err != nil {
		return nil, err
	}

	return m, nil
}

func GetMetaUUID(分类 string, meta map[string]interface{}) (x string) {
	switch 分类 {
	case "图标":
		subMetas := maputil.Map(meta, "subMetas")
		for _, isubMeta := range subMetas {
			subMeta := isubMeta.(map[string]interface{})
			subImporter := maputil.String(subMeta, "importer")
			if subImporter == "sprite-frame" {
				return maputil.String(subMeta, "uuid")
			}
		}
	}
	return mapx.String(meta, "uuid")
}
